// nolint: unused
package main

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"math/rand/v2"
	"net"
	"net/http"
	"net/url"
	"os"
	"smart-flow/server/config"
	"strings"
	"sync"
	"time"

	"github.com/go-redis/redis/v8"
	"github.com/lionsoul2014/ip2region/binding/golang/xdb"
	"github.com/showwin/speedtest-go/speedtest"
)

var RdbTerminal *redis.Client
var RdbCenter *redis.Client
var dataCleanChan = make(chan string, 1000)

func main() {
	// getUnknownIsp()
	// loadCmIps()
	// location("171.12.137.93")
	// getUidByIp("182.32.54.86")

	// getTimeStatus()
	// addTask(config.IspTelecom, "5000")
	// addTask(config.IspMobile, "10000")
	// stop()
	// delTask(config.IspTelecom)
	// delTask(config.IspMobile)
	// task()
	// pauseTask()
	// resumeTask()

	// dataClean()

	// testFun()
	// speedTest("http://58.221.63.11:8181/Stream")
	// speedTest("http://58.221.63.13:8181/Stream")
	// speedTest("")

	// genAsnFile()
}

func loadCmIps() {
	file, err := os.Open("../server/resource/cm-ips.conf")
	if err != nil {
		fmt.Printf("打开文件失败: %v\n", err)
		return
	}
	defer func(file *os.File) {
		_ = file.Close()
	}(file)
	var ipList []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		cidr := scanner.Text()
		if strings.TrimSpace(cidr) == "" {
			continue
		}
		if len(strings.Split(cidr, "/")) != 2 {
			continue
		}
		ipList = append(ipList, generateUsableIps(cidr)...)
	}
	fmt.Println(len(ipList), ipList[:5], ipList[len(ipList)-5:])
}

func generateUsableIps(cidr string) []string {
	var ips []string
	_, ipNet, err := net.ParseCIDR(cidr) // 解析CIDR地址
	if err != nil {
		if ip := net.ParseIP(cidr); ip != nil { // 如果解析失败，尝试作为单独的IP地址处理（假设掩码为32）
			ips = append(ips, cidr)
		}
		return ips
	}
	ones, bits := ipNet.Mask.Size() // 从IPNet获取掩码大小
	if bits == 128 {                // IPv6地址处理
		ips = append(ips, ipNet.IP.String())
	}
	if ones == 32 { // 如果是32位掩码，直接返回该IP
		ips = append(ips, ipNet.IP.String())
	} else if ones == 31 { // 如果是31位掩码，返回两个IP地址（特殊情况下没有网络地址和广播地址的区别）
		for ip := ipNet.IP.Mask(ipNet.Mask); ipNet.Contains(ip); incIp(ip) {
			ips = append(ips, ip.String())
		}
	} else { // 对于其他掩码，需要排除网络地址和广播地址
		first := true
		for ip := ipNet.IP.Mask(ipNet.Mask); ipNet.Contains(ip); incIp(ip) {
			if first { // 跳过网络地址（第一个IP）
				first = false
				continue
			}
			nextIP := make(net.IP, len(ip))
			copy(nextIP, ip)
			incIp(nextIP)
			if !ipNet.Contains(nextIP) { // 检查是否为广播地址（最后一个IP），如果是则跳过
				break
			}
			ips = append(ips, ip.String())
		}
	}
	return ips
}

func incIp(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}

func location(ip string) {
	dbPath := "../server/resource/ip2region.xdb"
	cBuff, err := xdb.LoadContentFromFile(dbPath) // 全量加载到内存
	if err != nil {
		fmt.Printf("加载数据失败: %v\n", err)
		return
	}
	searcher, err := xdb.NewWithBuffer(cBuff) // 内存查询器
	if err != nil {
		fmt.Printf("创建查询器失败: %v\n", err)
		return
	}
	defer searcher.Close()
	start := time.Now()
	region, err := searcher.SearchByStr(ip)
	if err != nil {
		fmt.Printf("查询失败: %v\n", err)
		return
	}
	fmt.Printf("结果: %s, 耗时: %v\n", region, time.Since(start))
}

func stop() {
	// urlStr := "http://127.0.0.1:8080/sf/Flow/Stop"
	urlStr := "http://lcinter.aginomoto.com/sf/Flow/Stop"
	formData := url.Values{}
	formData.Add("isp", config.IspTelecom)
	resp, err := http.Post(urlStr, "application/x-www-form-urlencoded", strings.NewReader(formData.Encode()))
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)
	data, _ := io.ReadAll(resp.Body)
	fmt.Printf("返回数据：%s, 状态码: %d\n", string(data), resp.StatusCode)
}

func stopOne(uid string) {
	urlStr := "http://127.0.0.1:8080/sf/Flow/StopOne"
	// urlStr := "http://lcinter.aginomoto.com/sf/Flow/StopOne"
	formData := url.Values{}
	formData.Add("uid", uid)
	resp, err := http.Post(urlStr, "application/x-www-form-urlencoded", strings.NewReader(formData.Encode()))
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)
	data, _ := io.ReadAll(resp.Body)
	fmt.Printf("返回数据：%s, 状态码: %d\n", string(data), resp.StatusCode)
}

func task() {
	// urlStr := "http://127.0.0.1:8080/sf/Task/List"
	urlStr := "http://lcinter.aginomoto.com/sf/Task/List"
	resp, err := http.Get(urlStr)
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)
	data, _ := io.ReadAll(resp.Body)
	fmt.Printf("返回数据：%s, 状态码: %d\n", string(data), resp.StatusCode)
}

func addTask(isp, rate string) {
	// urlStr := "http://127.0.0.1:8080/sf/Task/Add"
	urlStr := "http://lcinter.aginomoto.com/sf/Task/Add"
	formData := url.Values{}
	formData.Add("isp", isp)
	formData.Add("exIncProvince", "江苏省")
	formData.Add("runDuration", "525600")
	formData.Add("runRate", rate)
	formData.Add("runCycle", "0")
	formData.Add("runTimeHour", "22")
	formData.Add("runTimeMinute", "58")
	if isp == config.IspTelecom {
		formData.Add("runTimeSecond", "15")
		formData.Add("v4Enabled", "1")
		formData.Add("v6Enabled", "1")
	} else {
		formData.Add("runTimeSecond", "45")
		formData.Add("v4Enabled", "1")
		formData.Add("v6Enabled", "0")
	}
	resp, err := http.Post(urlStr, "application/x-www-form-urlencoded", strings.NewReader(formData.Encode()))
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)
	data, _ := io.ReadAll(resp.Body)
	fmt.Printf("返回数据：%s, 状态码: %d\n", string(data), resp.StatusCode)
}

func delTask(isp string) {
	// urlStr := "http://127.0.0.1:8080/sf/Task/Del"
	urlStr := "http://lcinter.aginomoto.com/sf/Task/Del"
	formData := url.Values{}
	formData.Add("isp", isp)
	resp, err := http.Post(urlStr, "application/x-www-form-urlencoded", strings.NewReader(formData.Encode()))
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)
	data, _ := io.ReadAll(resp.Body)
	fmt.Printf("返回数据：%s, 状态码: %d\n", string(data), resp.StatusCode)
}

func pauseTask() {
	// urlStr := "http://127.0.0.1:8080/sf/Task/GlobalPause"
	urlStr := "http://lcinter.aginomoto.com/sf/Task/GlobalPause"
	formData := url.Values{}
	formData.Add("isp", config.IspTelecom)
	resp, err := http.Post(urlStr, "application/x-www-form-urlencoded", strings.NewReader(formData.Encode()))
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)
	data, _ := io.ReadAll(resp.Body)
	fmt.Printf("返回数据：%s, 状态码: %d\n", string(data), resp.StatusCode)
}

func resumeTask() {
	// urlStr := "http://127.0.0.1:8080/sf/Task/GlobalResume"
	urlStr := "http://lcinter.aginomoto.com/sf/Task/GlobalResume"
	formData := url.Values{}
	formData.Add("isp", config.IspTelecom)
	resp, err := http.Post(urlStr, "application/x-www-form-urlencoded", strings.NewReader(formData.Encode()))
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)
	data, _ := io.ReadAll(resp.Body)
	fmt.Printf("返回数据：%s, 状态码: %d\n", string(data), resp.StatusCode)
}

func getUidByIp(ip string) {
	// urlStr := "http://127.0.0.1:8080/sf/Test/GetUid"
	urlStr := "http://lcinter.aginomoto.com/sf/Test/GetUid"
	formData := url.Values{}
	formData.Add("ip", ip)
	resp, err := http.Post(urlStr, "application/x-www-form-urlencoded", strings.NewReader(formData.Encode()))
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)
	data, _ := io.ReadAll(resp.Body)
	fmt.Printf("返回数据：%s, 状态码: %d\n", string(data), resp.StatusCode)
}

func getTimeStatus() int {
	now := time.Now()
	// 获取今天的日期
	year, month, day := now.Date()
	// 创建今天的18:00时间点
	cutoff18 := time.Date(year, month, day, 18, 0, 0, 0, now.Location())
	// 创建今天的22:10时间点
	cutoff2210 := time.Date(year, month, day, 22, 10, 0, 0, now.Location())
	// 如果当前时间在18:00之前
	if now.Before(cutoff18) {
		sub := int(now.Sub(time.Date(year, month, day, 0, 0, 0, 0, now.Location())).Minutes())
		fmt.Println(sub)
		return sub
	}
	// 如果当前时间在18:00到22:10之间
	if now.After(cutoff18) && now.Before(cutoff2210) {
		fmt.Println(-1)
		return -1
	}
	// 如果当前时间在22:10之后
	fmt.Println(0)
	return 0
}

func getUnknownIsp() {
	dbPath := "../server/resource/ip2region.xdb"
	cBuff, err := xdb.LoadContentFromFile(dbPath) // 全量加载到内存
	if err != nil {
		fmt.Printf("加载数据失败: %v\n", err)
		return
	}
	searcher, err := xdb.NewWithBuffer(cBuff) // 内存查询器
	if err != nil {
		fmt.Printf("创建查询器失败: %v\n", err)
		return
	}
	defer searcher.Close()
	RdbTerminal = redis.NewClient(&redis.Options{
		Addr: "10.19.156.119:6379",
		// Addr:     "172.16.17.88:6379",
		Password: "",
		DB:       0,
		PoolSize: 10,
	})
	var (
		nextCursor   uint64
		data         []string
		count        int
		unknownCount int
	)

	type LcClient struct {
		Ip string `json:"ip"`
	}
	for {
		data, nextCursor, err = RdbTerminal.HScan(context.Background(), "client", nextCursor, "whaley_*", 1000).Result()
		if err != nil {
			return
		}
		for i := 0; i < len(data); i += 2 {
			count++
			uid := data[i]
			var lcClient LcClient
			_ = json.Unmarshal([]byte(data[i+1]), &lcClient)
			if lcClient.Ip == "" {
				continue
			}
			regionInfo, _ := searcher.SearchByStr(lcClient.Ip)
			if !strings.Contains(regionInfo, "电信") && !strings.Contains(regionInfo, "移动") && !strings.Contains(regionInfo, "联通") {
				unknownCount++
				fmt.Printf("uid: %s, region: %s\n", uid, regionInfo)
			}
		}
		if nextCursor == 0 {
			fmt.Println(count, unknownCount)
			return
		}
	}
}

func dataClean() {
	connectRedis()
	go dataCleanScan()
	dataCleanWorker()
}

func connectRedis() {
	RdbTerminal = redis.NewClient(&redis.Options{
		// Addr: "10.19.156.119:6379",
		Addr:     "172.16.17.88:6379",
		Password: "",
		DB:       3,
		PoolSize: 10,
	})
	RdbCenter = redis.NewClient(&redis.Options{
		// Addr: "10.19.158.116:6379",
		Addr:     "172.16.17.88:6379",
		Password: "",
		DB:       3,
		PoolSize: 10,
	})
}

func dataCleanScan() {
	defer close(dataCleanChan)
	var nextCursor uint64 = 0
	var data []string
	var err error
	for {
		data, nextCursor, err = RdbTerminal.HScan(context.Background(), "client", nextCursor, "*", 1000).Result()
		if err != nil {
			return
		}
		for i := 0; i < len(data); i += 2 {
			uid := data[i]
			dataCleanChan <- uid
		}
		if nextCursor == 0 {
			return
		}
	}
}

func dataCleanWorker() {
	for uid := range dataCleanChan {
		exist, err := RdbCenter.HExists(context.Background(), "client_host_info", uid).Result()
		if err != nil {
			return
		}
		if !exist {
			RdbTerminal.HDel(context.Background(), "client", uid)
		}
	}
}

func testFun() {
	var wg sync.WaitGroup
	for i := 0; i < 50; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			// 生成随机数
			fmt.Printf("Goroutine %d: %d\n", id, rand.IntN(100))
		}(i)
	}
	wg.Wait()
}

func speedTest(addr string) {
	var s = speedtest.New()
	s.SetCaptureTime(5 * time.Second)
	var server *speedtest.Server
	var err error
	if addr == "" {
		servers, _ := s.FetchServers()
		for _, srv := range servers {
			fmt.Printf("server: %v\n", srv)
		}
		servers, _ = servers.FindServer([]int{})
		server = servers[0]
	} else {
		server, err = s.CustomServer(addr)
		if err != nil {
			return
		}
		server.URL = addr
	}
	//if err = server.UploadTest(); err == nil {
	//	fmt.Println(server.ULSpeed * 8 / 1000 * 1000)
	//} else {
	//	fmt.Printf("上行带宽测试失败: %v\n", err)
	//}
}

type AsnResponse struct {
	Status        string `json:"status"`
	StatusMessage string `json:"status_message"`
	Data          struct {
		IPv6Prefixes []struct {
			Prefix      string `json:"prefix"`
			IP          string `json:"ip"`
			Cidr        int    `json:"cidr"`
			RoaStatus   string `json:"roa_status"`
			Name        string `json:"name"`
			Description string `json:"description"`
			CountryCode string `json:"country_code"`
		} `json:"ipv6_prefixes"`
	} `json:"data"`
}

type AsnRecordV6 struct {
	Ip   string `json:"ip"`
	Cidr int    `json:"cidr"`
}

func genAsnFile() {
	urlList := []string{
		"https://api.bgpview.io/asn/4134/prefixes",
	}
	for _, urlStr := range urlList {
		data := httpGet(urlStr)
		if len(data) == 0 {
			return
		}
		var res AsnResponse
		if err := json.Unmarshal(data, &res); err != nil {
			return
		}
		if res.Status != "ok" {
			return
		}
		for _, record := range res.Data.IPv6Prefixes {
			if record.CountryCode != "CN" ||
				record.Description != "Chinatelecom networks with tens of high-end routers and switches" ||
				!strings.HasPrefix(record.IP, "240e:3") {
				continue
			}
			asnRecordV6 := AsnRecordV6{
				Ip:   record.IP,
				Cidr: record.Cidr,
			}
			fmt.Println(asnRecordV6.Ip, asnRecordV6.Cidr)
			time.Sleep(1 * time.Second)
		}
	}
}

func httpGet(urlStr string) []byte {
	client := &http.Client{}
	req, err := http.NewRequest("GET", urlStr, nil)
	if err != nil {
		fmt.Printf("创建请求失败: %v\n", err)
		return nil
	}
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36")
	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("请求失败: %v\n", err)
		return nil
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(resp.Body)
	data, _ := io.ReadAll(resp.Body)
	// fmt.Printf("返回数据：%s, 状态码: %d\n", string(data), resp.StatusCode)
	return data
}

/*
240e:304:: 30  	北京
240e:308:: 30	黑龙江
240e:30c:: 30	辽宁
240e:310:: 30	吉林
240e:314:: 30	海南
240e:318:: 32	内蒙古
240e:319:: 32	内蒙古
240e:31c:: 30	宁夏
240e:320:: 30	青海
240e:325:: 32	山西
240e:326:: 32	山西
240e:327:: 32	山西
240e:32c:: 30	西藏
240e:330:: 30	重庆
240e:334:: 30	甘肃
240e:33c:: 30	河南
240e:340:: 32	河北
240e:341:: 32	河北
240e:342:: 32	河北
240e:343:: 32	河北
240e:344:: 30	山东
240e:348:: 30	新疆
240e:34c:: 30	云南
240e:350:: 29	广西
240e:358:: 29	陕西
240e:360:: 29	安徽
240e:368:: 29	湖北
240e:370:: 29	江西
240e:378:: 29	福建
240e:380:: 29	湖南
240e:388:: 29	上海
240e:390:: 29	浙江
240e:398:: 29	四川
240e:3a0:: 28	江苏
240e:3b0:: 28	广东
*/
